import { Process } from '../actor/process';
import { PID } from '../actor/pid';
import { EndpointManager } from './endpointManager';
import { RemoteMessageType } from './remote';

export interface RemoteMessage {
  type: RemoteMessageType;
  targetPID: PID;
  message: any;
  messageId?: string;
  senderPID?: PID;
}

/**
 * 准备远程消息，确保没有循环引用
 * @param message 原始消息
 * @returns 处理后的消息，保证可序列化
 */
export function prepareRemoteMessage(message: RemoteMessage): any {
  console.log(`[REMOTE_PROCESS] Preparing remote message of type: ${message.type}`);
  
  // 创建基本消息结构
  const prepared: any = {
    type: message.type,
    targetPID: message.targetPID ? {
      address: message.targetPID.address,
      id: message.targetPID.id
    } : undefined,
    messageId: message.messageId,
    senderPID: message.senderPID ? {
      address: message.senderPID.address,
      id: message.senderPID.id
    } : undefined
  };
  
  // 处理消息
  if (message.message === null || message.message === undefined) {
    prepared.message = message.message;
  } else if (typeof message.message !== 'object') {
    // 基本类型
    prepared.message = message.message;
  } else {
    // 对于对象类型的消息，需要特殊处理
    const msgObj: any = message.message;
    
    // 检查是否是信封格式
    if ('message' in msgObj && 'sender' in msgObj) {
      console.log(`[REMOTE_PROCESS] Processing envelope message`);
      
      // 创建安全的信封副本
      const safeSender = msgObj.sender ? {
        address: msgObj.sender.address,
        id: msgObj.sender.id
      } : undefined;
      
      prepared.message = {
        message: msgObj.message,
        sender: safeSender
      };
      
      console.log(`[REMOTE_PROCESS] Prepared envelope with sender: ${JSON.stringify(safeSender)}`);
    } else {
      // 其他对象类型，创建浅层副本
      prepared.message = { ...msgObj };
      
      // 确保不包含循环引用
      Object.keys(prepared.message).forEach(key => {
        const value = prepared.message[key];
        
        // 处理可能包含 PID 的属性
        if (value && typeof value === 'object') {
          if ('address' in value && 'id' in value) {
            prepared.message[key] = {
              address: value.address,
              id: value.id
            };
          } else if (typeof value === 'function') {
            // 移除函数引用
            delete prepared.message[key];
          }
        }
      });
      
      console.log(`[REMOTE_PROCESS] Prepared generic object message`);
    }
  }

  // 验证序列化
  try {
    JSON.stringify(prepared);
    console.log(`[REMOTE_PROCESS] Message successfully serialized`);
  } catch (error: any) {
    console.error(`[REMOTE_PROCESS] Serialization failed: ${error.message}`);
    console.error(`[REMOTE_PROCESS] Problematic keys:`, Object.keys(prepared));
    
    // 尝试更激进的清理
    prepared.message = typeof prepared.message === 'object' ? 
      JSON.parse(JSON.stringify({ value: prepared.message.toString() })).value : 
      String(prepared.message);
  }
  
  return prepared;
}

export class RemoteProcess implements Process {
  private readonly pid: PID;
  private readonly endpointManager: EndpointManager;

  constructor(pid: PID, endpointManager: EndpointManager) {
    this.pid = pid;
    this.endpointManager = endpointManager;
    console.log(`[REMOTE_PROCESS] Created RemoteProcess for PID: ${JSON.stringify(pid)}`);
  }

  // 发送用户消息
  sendUserMessage(pid: PID, message: any): void {
    console.log(`[REMOTE_PROCESS] Sending user message from ${this.pid.toString()} to ${pid.toString()}`);
    console.log(`[REMOTE_PROCESS] Message type: ${typeof message}, isEnvelope: ${'sender' in message && 'message' in message}`);
    
    this.sendRemoteMessage({
      type: RemoteMessageType.Normal,
      targetPID: pid,
      message: message,
      messageId: `${Date.now()}-${Math.floor(Math.random() * 1000000)}`,
      senderPID: this.pid
    });
  }

  // 发送系统消息
  sendSystemMessage(pid: PID, message: any): void {
    console.log(`Sending system message from ${this.pid.toString()} to ${pid.toString()}:`, message);
    this.sendRemoteMessage({
      type: RemoteMessageType.System,
      targetPID: pid,
      message: message,
      messageId: `${Date.now()}-${Math.floor(Math.random() * 1000000)}`,
      senderPID: this.pid
    });
  }

  // 停止进程
  stop(pid: PID): void {
    console.log(`Stopping remote process: ${pid.toString()}`);
    this.sendSystemMessage(pid, { type: 'stop' });
  }

  // 发送远程消息
  private async sendRemoteMessage(msg: RemoteMessage): Promise<void> {
    try {
      const targetAddress = msg.targetPID?.address;
      console.log(`[REMOTE_PROCESS] Sending remote message to ${targetAddress}, message type: ${msg.type}`);
      console.log(`[REMOTE_PROCESS] Target PID: ${msg.targetPID?.address}/${msg.targetPID?.id}`);
      
      if (msg.senderPID) {
        console.log(`[REMOTE_PROCESS] Sender PID: ${msg.senderPID.address}/${msg.senderPID.id}`);
      }
      
      if (!targetAddress) {
        console.error(`[REMOTE_PROCESS] Target address is missing in the message`);
        throw new Error('Target address is required for remote message');
      }

      if (targetAddress === 'local') {
        console.error(`[REMOTE_PROCESS] Cannot send remote message to local address`);
        throw new Error('Cannot send remote message to local address');
      }

      // 准备消息，避免循环引用
      console.log(`[REMOTE_PROCESS] Preparing message for serialization...`);
      const preparedMessage = prepareRemoteMessage(msg);
      console.log(`[REMOTE_PROCESS] Message preparation complete`);

      // 验证准备好的消息
      try {
        const serializedMsg = JSON.stringify(preparedMessage);
        console.log(`[REMOTE_PROCESS] Message successfully serialized, length: ${serializedMsg.length}`);
      } catch (error: any) {
        console.error(`[REMOTE_PROCESS] Message serialization verification failed: ${error.message}`);
        console.error(`[REMOTE_PROCESS] Problematic message:`, preparedMessage);
        throw new Error(`Cannot serialize message: ${error.message}`);
      }

      console.log(`[REMOTE_PROCESS] Sending message to endpoint manager...`);
      try {
        await this.endpointManager.sendMessage(targetAddress, preparedMessage);
        console.log(`[REMOTE_PROCESS] Message sent successfully to ${targetAddress}`);
      } catch (error: any) {
        console.error(`[REMOTE_PROCESS] Error from endpoint manager: ${error.message}`);
        throw error;
      }
    } catch (error: any) {
      console.error(`[REMOTE_PROCESS] Failed to send remote message: ${error.message}`);
      console.error(`[REMOTE_PROCESS] Error stack: ${error.stack}`);
      throw error;
    }
  }
} 